package uni.androidgame;

import android.content.Context;
import android.graphics.Canvas;
import android.support.v4.view.MotionEventCompat;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.ArrayList;

import uni.androidgame.gameobjects.DungeonMap;
import uni.androidgame.gameobjects.Item;
import uni.androidgame.gameobjects.Monster;
import uni.androidgame.gameobjects.Player;
import uni.androidgame.gameobjects.Tile;
import uni.androidgame.mapgeneration.MapGenerator;

public class GameView extends SurfaceView implements SurfaceHolder.Callback
{

    private DungeonMap _currentDungeonMap;
    private Player _player;
    private ArrayList<Monster> monsters = new ArrayList<Monster>();
    private Item _itemToThrow;
    private GameAction _playerAction;
    private ArrayList<GameAction> _newActions = new ArrayList<GameAction>();
    private GameStateUpdater _gameStateUpdater = new GameStateUpdater();

    private Boolean _isPaused = false;
    private SurfaceHolder surfaceHolder;
    private DrawThread _drawThread;
    private Context _context;
    private int gameSpeedCounter = 0;
    private final int gameSpeed = 1;


    private ScaleGestureDetector _scaleGestureDetector;
    private float scaleFactor = 1.0f;

    private float _lastTouchedX = -1;
    private float _lastTouchedY = -1;
    private float _moveX = 0;
    private float _moveY = 0;

    public GameView(Context context)
    {

        super(context);

        _context = context;
        surfaceHolder = getHolder();
        try
        {
            surfaceHolder.addCallback(this);
        }
        catch (NullPointerException npe)
        {
            throw new NullPointerException("Unable to retrieve surfaceHolder");
        }
        _scaleGestureDetector= new ScaleGestureDetector(context,new ScaleListener());
    }


    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder)
    {
        setWillNotDraw(false);
        _drawThread = new DrawThread(surfaceHolder,_context,this);
        _drawThread.set_isRunning(true);
        _drawThread.start();

        GameConsole.setup(10,getHeight()-80);
        createNewDungeon();

    }

    private void createNewDungeon()
    {
        _currentDungeonMap= MapGenerator.generateMap(20, 20);
        //_currentDungeonMap.setNeighbourTiles();
        _player = _currentDungeonMap.createPlayer();
        monsters = _currentDungeonMap.createMonsters(2);
        _gameStateUpdater.setCharactersToUpdate(monsters,_player);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //_scaleGestureDetector.onTouchEvent(event);
        //updateFingerState(event);

        Tile touchedTile = _currentDungeonMap.getTouchedTile(event.getX(), event.getY());
        if(touchedTile != null && touchedTile != _player.getCurrentTile())
        {
            if(_itemToThrow != null)
            {
                _player.setThrowAction(_itemToThrow,touchedTile);
            }
            else if( touchedTile.getCharacter() != null && touchedTile.getCharacter() != _player)
            {
                if(!touchedTile.isAdjacent(_player.getCurrentTile()))
                {
                    ArrayList<Tile> pathToEnemy = PathFinder.getPath(_player.getCurrentTile(),touchedTile);
                    if(pathToEnemy != null)
                    {
                        pathToEnemy.remove(pathToEnemy.size()-1);
                        _player.setMovementActions(pathToEnemy);
                        _player.setAttackAction(touchedTile);
                    }
                }
                else
                {
                    _player.setAttackAction(touchedTile);
                }
            }
            else
            {
                ArrayList<Tile> playerPath = PathFinder.getPath(_player.getCurrentTile(),touchedTile);

                if(playerPath != null)
                {
                    _player.setMovementActions(playerPath);
                }
            }
        }
        return super.onTouchEvent(event);
    }



    private void update()
    {
        if(!_isPaused)
        {
            _gameStateUpdater.updateGameState();
        }
    }
    @Override
    protected void onDraw(Canvas canvas)
    {
        //canvas.save();
        //canvas.scale(scaleFactor,scaleFactor);
        //canvas.translate(_moveX,_moveY);
        //_currentDungeonMap.draw(canvas);


        //Drawing
        _player.draw(canvas);
        for(Monster monster : monsters)
        {
            monster.draw(canvas);
        }
        GameConsole.draw(canvas);

        update();

        //canvas.restore();
        _moveX = _moveY = 0;
        invalidate();
    }
    private void updateFingerState(MotionEvent event)
    {
        final int action = MotionEventCompat.getActionMasked(event);
        final int pointerIndex = MotionEventCompat.getActionIndex(event);
        switch(action)
        {
            case MotionEvent.ACTION_DOWN:

                _lastTouchedX = MotionEventCompat.getX(event,pointerIndex);
                _lastTouchedY = MotionEventCompat.getY(event,pointerIndex);
                break;
            case MotionEvent.ACTION_MOVE:
                final float x = MotionEventCompat.getX(event,pointerIndex);
                final float y = MotionEventCompat.getY(event,pointerIndex);
                _moveX = _lastTouchedX-x;
                _moveY = _lastTouchedY-y;
                _lastTouchedX = x;
                _lastTouchedY = y;
                break;
            case MotionEvent.ACTION_UP:
                break;

        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3)
    {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder)
    {

    }
    private class ScaleListener
            extends ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        @Override
        public boolean onScale(ScaleGestureDetector detector)
        {
            scaleFactor *= detector.getScaleFactor();

            // Don't let the object get too small or too large.
            scaleFactor = Math.max(0.5f, Math.min(scaleFactor, 2f));

            invalidate();
            return true;
        }
    }
}

